home *** CD-ROM | disk | FTP | other *** search
- /* writeps.c - routines to output PostScript representation of object
- * - using TTDDDLIB by Glenn M. Lewis - 7/23/91
- */
-
- static char rcs_id[] = "$Id: writeps.c,v 1.18 1993/01/30 12:55:49 glewis Exp $";
-
- #include <stdio.h>
- #include "t3dlib.h"
- #ifdef __STDC__
- #include <stdlib.h>
- #include <strings.h>
- #include "writeps_protos.h"
- #endif
-
- double XSIZE = 8.5;
- double YSIZE = 11.0;
- #define EXTRASPACE 0.95
- #define MARGIN (0.25) /* On each side of the page */
- #define PPI (72.0)
- #define COS60 (0.5)
- #define COS30 (0.8660)
-
- static void write_PS_header();
- static void draw_PS_view();
- static void render_PS_object();
-
- static FILE *out;
- static WORLD *world;
- static MBB mbb;
- static double xsize, ysize;
- static int view;
- static double xoffset, yoffset, scale, ybottom;
-
- void calculate_MBB_world(world)
- WORLD *world;
- {
- register OBJECT *obj;
-
- if (!world) return;
-
- /* Determine the extent of the world object */
- mbb.minx = mbb.miny = mbb.minz = 1.0e10;
- mbb.maxx = mbb.maxy = mbb.maxz = -1.0e10;
- for (obj=world->object; obj; obj=obj->next) {
- calculate_MBB(obj);
- if (!obj->user) continue;
- if (((MBB*)obj->user)->minx<mbb.minx) mbb.minx=((MBB*)obj->user)->minx;
- if (((MBB*)obj->user)->miny<mbb.miny) mbb.miny=((MBB*)obj->user)->miny;
- if (((MBB*)obj->user)->minz<mbb.minz) mbb.minz=((MBB*)obj->user)->minz;
- if (((MBB*)obj->user)->maxx>mbb.maxx) mbb.maxx=((MBB*)obj->user)->maxx;
- if (((MBB*)obj->user)->maxy>mbb.maxy) mbb.maxy=((MBB*)obj->user)->maxy;
- if (((MBB*)obj->user)->maxz>mbb.maxz) mbb.maxz=((MBB*)obj->user)->maxz;
- }
- world->user = (void*)&mbb;
- }
-
- int write_PostScript(object, file, selected_view)
- WORLD *object;
- FILE *file;
- int selected_view;
- {
- double llx, lly;
- if (!(out = file)) return(0); /* File not open */
- if (!(world = object)) return(0); /* No object */
-
- calculate_MBB_world(world);
-
- #ifdef DEBUG
- fprintf(stderr, "MBB: (%.12g,%.12g,%.12g)-(%.12g,%.12g,%.12g)\n",
- mbb.minx, mbb.miny, mbb.minz,
- mbb.maxx, mbb.maxy, mbb.maxz);
- #endif
-
- write_PS_header();
- if (selected_view==VIEW_ALL_FOUR) {
- for (view=0; view<4; view++) {
- llx = ((view&0x02) ? XSIZE/2.0 : MARGIN) * PPI;
- lly = ((view&0x01) ? MARGIN : YSIZE/2.0) * PPI;
- xsize = PPI*(XSIZE/2.0 - MARGIN);
- ysize = PPI*(YSIZE/2.0 - MARGIN);
- fprintf(out, "gsave\n0.1 setlinewidth\n%.12g %.12g translate\n", llx, lly);
- draw_PS_view();
- fprintf(out, "grestore\n");
- }
- } else {
- xsize = PPI*(XSIZE - 2.0*MARGIN);
- ysize = PPI*(YSIZE - 2.0*MARGIN);
- fprintf(out,"0.1 setlinewidth\n%.12g %.12g translate\n",PPI*MARGIN,PPI*MARGIN);
- view=selected_view;
- draw_PS_view();
- }
- fprintf(out, "showpage\n");
- return(1);
- }
-
- void calculate_MBB(obj)
- OBJECT *obj;
- {
- OBJECT *child;
- register XYZ_st *p;
- register int i;
- MBB *mbb;
- double x, y, z;
-
- if (!obj) return;
- if (!obj->desc && !obj->child) return; /* Not an object */
- if (obj->user) { free((char*)obj->user); obj->user=0; }
-
- if (!(mbb = (MBB*)malloc(sizeof(MBB)))) {
- fputs("Out of memory", out); exit(-1); }
- mbb->minx = mbb->miny = mbb->minz = 1.0e10;
- mbb->maxx = mbb->maxy = mbb->maxz = -1.0e10;
-
- /* Account for children... */
- for (child=obj->child; child; child=child->next) {
- calculate_MBB(child);
- if (!child->user) continue;
- if (((MBB*)child->user)->minx < mbb->minx)
- mbb->minx = ((MBB*)child->user)->minx;
- if (((MBB*)child->user)->miny < mbb->miny)
- mbb->miny = ((MBB*)child->user)->miny;
- if (((MBB*)child->user)->minz < mbb->minz)
- mbb->minz = ((MBB*)child->user)->minz;
- if (((MBB*)child->user)->maxx > mbb->maxx)
- mbb->maxx = ((MBB*)child->user)->maxx;
- if (((MBB*)child->user)->maxy > mbb->maxy)
- mbb->maxy = ((MBB*)child->user)->maxy;
- if (((MBB*)child->user)->maxz > mbb->maxz)
- mbb->maxz = ((MBB*)child->user)->maxz;
- }
-
- x = y = z = 0.0;
- /*
- if (obj->desc->posi) {
- x = obj->desc->posi->x;
- y = obj->desc->posi->y;
- z = obj->desc->posi->z;
- fprintf(out, "position: %lx (%.12g,%.12g,%.12g)\n", (unsigned long)obj,x,y,z);
- }
- */
- for (p=obj->desc->pnts,i=obj->desc->pcount; i--; p++) {
- if (p->x-x < mbb->minx) mbb->minx = p->x-x;
- if (p->y-y < mbb->miny) mbb->miny = p->y-y;
- if (p->z-z < mbb->minz) mbb->minz = p->z-z;
- if (p->x-x > mbb->maxx) mbb->maxx = p->x-x;
- if (p->y-y > mbb->maxy) mbb->maxy = p->y-y;
- if (p->z-z > mbb->maxz) mbb->maxz = p->z-z;
- }
- obj->user = (void *)mbb;
- #ifdef DEBUG
- fprintf(stderr, "MBB: %lx child:%lx next:%lx (%.12g,%.12g,%.12g)-(%.12g,%.12g,%.12g)\n",
- (unsigned long)obj,
- (unsigned long)obj->child,
- (unsigned long)obj->next,
- mbb->minx, mbb->miny, mbb->minz,
- mbb->maxx, mbb->maxy, mbb->maxz);
- #endif
- }
-
- static void write_PS_header()
- {
- fputs("%! PS-Adobe-2.0 EPSF-1.2\n", out);
- fprintf(out, "%%%%BoundingBox: %.12g %.12g %.12g %.12g\n",
- PPI*MARGIN, PPI*MARGIN, PPI*(XSIZE-2.0*MARGIN), PPI*(YSIZE-2.0*MARGIN));
- fputs("%%Creator: TTDDDLIB by Glenn M. Lewis\n", out);
- fputs("%%EndComments\n%%BeginSetup\n", out);
- fputs("/M {moveto} bind def\n", out);
- fputs("/D {lineto} bind def\n", out);
- fputs("/S {stroke} bind def\n", out);
- fputs("%%EndSetup\n", out);
- }
-
- static void draw_PS_view()
- {
- double xratio, yratio, zratio;
- OBJECT *obj;
- fprintf(out, "0 0 M %.12g 0 D %.12g %.12g D 0 %.12g D 0 0 D S\n",
- xsize, xsize, ysize, ysize);
-
- if (mbb.maxx-mbb.minx>0.0) xratio=1.0/(mbb.maxx-mbb.minx); else xratio=1.0;
- if (mbb.maxy-mbb.miny>0.0) yratio=1.0/(mbb.maxy-mbb.miny); else yratio=1.0;
- if (mbb.maxz-mbb.minz>0.0) zratio=1.0/(mbb.maxz-mbb.minz); else zratio=1.0;
- scale = (ysize*yratio < xsize*yratio ? ysize*yratio : xsize*yratio);
- scale = (scale < ysize*zratio ? scale : ysize*zratio);
- scale = (scale < xsize*xratio ? scale : xsize*xratio);
- /* Scale makes it fit exactly into the area. Expand it a little */
- scale *= EXTRASPACE;
-
- switch(view) {
- case VIEW_TOP:
- fputs("% Top view\n", out);
- xoffset = (xsize-scale/xratio)/2.0;
- yoffset = (ysize-scale/yratio)/2.0;
- break;
- case VIEW_FRONT:
- fputs("% Front view\n", out);
- xoffset = (xsize-scale/xratio)/2.0;
- yoffset = (ysize-scale/zratio)/2.0;
- break;
- case VIEW_ISO:
- fputs("% Isometric view\n", out);
- xratio = (mbb.maxx-mbb.minx)*COS30+(mbb.maxy-mbb.miny)*COS30;
- if (xratio>0.0) xratio = 1.0/xratio; else xratio=1.0;
- ybottom = -(mbb.maxx-mbb.minx)*COS60;
- yratio = (mbb.maxz-mbb.minz)+(mbb.maxy-mbb.miny)*COS60 /* Top */
- - ybottom;
- if (yratio>0.0) yratio = 1.0/yratio; else yratio=1.0;
- scale = (xsize*xratio < ysize*yratio ? xsize*xratio : ysize*yratio);
- scale *= EXTRASPACE;
- xoffset = (xsize-scale/xratio)/2.0;
- yoffset = (ysize-scale/yratio)/2.0;
- break;
- case VIEW_RIGHT:
- fputs("% Right view\n", out);
- xoffset = (xsize-scale/yratio)/2.0;
- yoffset = (ysize-scale/zratio)/2.0;
- break;
- }
- for (obj=world->object; obj; obj=obj->next)
- render_PS_object(obj);
- }
-
- static void render_PS_object(obj)
- register OBJECT *obj;
- {
- register UWORD *f;
- register OBJECT *op;
- register int i, j;
- int p[3];
- double x[3], y[3];
-
- if (!obj->desc) return;
- for (op=obj->child; op; op=op->next) /* render children first */
- render_PS_object(op);
-
- /* Now, the meat... */
- #if 0
- if (obj->desc->shap && obj->desc->shap[1]!=0) return; /* A lamp */
- #endif
- if (!obj->desc->edge || !obj->desc->pnts || !obj->desc->face) return;
- for (f=obj->desc->face,i=obj->desc->fcount; i--; f+=3) {
- p[0] = obj->desc->edge[((*f)<<1)];
- p[1] = obj->desc->edge[((*f)<<1)+1];
- if (obj->desc->edge[((f[1])<<1)] == p[0] ||
- obj->desc->edge[((f[1])<<1)] == p[1])
- p[2] = obj->desc->edge[((f[1])<<1)+1];
- else
- p[2] = obj->desc->edge[((f[1])<<1)];
- switch(view) {
- case VIEW_TOP:
- for (j=3; j--; ) {
- x[j] = obj->desc->pnts[p[j]].x-mbb.minx;
- y[j] = obj->desc->pnts[p[j]].y-mbb.miny;
- }
- break;
- case VIEW_FRONT:
- for (j=3; j--; ) {
- x[j] = obj->desc->pnts[p[j]].x-mbb.minx;
- y[j] = obj->desc->pnts[p[j]].z-mbb.minz;
- }
- break;
- case VIEW_ISO:
- for (j=3; j--; ) {
- x[j] = (obj->desc->pnts[p[j]].x-mbb.minx)*COS30
- +(obj->desc->pnts[p[j]].y-mbb.miny)*COS30;
- y[j] = (obj->desc->pnts[p[j]].z-mbb.minz)
- -(obj->desc->pnts[p[j]].x-mbb.minx)*COS60
- +(obj->desc->pnts[p[j]].y-mbb.miny)*COS60
- - ybottom;
- }
- break;
- case VIEW_RIGHT:
- for (j=3; j--; ) {
- x[j] = obj->desc->pnts[p[j]].y-mbb.miny;
- y[j] = obj->desc->pnts[p[j]].z-mbb.minz;
- }
- break;
- }
- if (x[0]==x[1] && x[1]==x[2] && y[0]==y[1] && y[1]==y[2]) continue;
- fprintf(out, "%0.2lf %0.2lf M ", xoffset+scale*x[0],yoffset+scale*y[0]);
- if (!(x[0]==x[1] && y[0]==y[1])) {
- fprintf(out, "%0.2lf %0.2lf D ",
- xoffset+scale*x[1], yoffset+scale*y[1]);
- }
- if (!(x[0]==x[2] && y[0]==y[2]) && !(x[1]==x[2] && y[1]==y[2])) {
- fprintf(out, "%0.2lf %0.2lf D ",
- xoffset+scale*x[2], yoffset+scale*y[2]);
- }
- fprintf(out, "%0.2lf %0.2lf D S\n",
- xoffset+scale*x[0],yoffset+scale*y[0]);
- }
- }
-